package ranking

import (
	"context"
	"strings"

	"gitee.com/wchpub/dwSvrPub/blocks/mainBlock"
	"gitee.com/wchpub/fnsvr"
	"github.com/redis/go-redis/v9"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
)

type RankingUserInfo struct {
	Name    string `bson:"name,omitempty" json:"name,omitempty"`
	OpenId  string `bson:"openid,omitempty" json:"openid,omitempty"`
	SkinId  int    `bson:"skinId,omitempty" json:"skinId,omitempty"`
	SkinIdx int    `bson:"skinIdx,omitempty" json:"skinIdx,omitempty"`
	Face    bool   `bson:"face,omitempty" json:"face,omitempty"` //是否上传了头像
}

// 排行榜上的用户信息
type MongoRankingUserInfo struct {
	ID primitive.ObjectID `bson:"_id"` // 强制映射为ObjectId类型
	RankingUserInfo
}

// mongo排行榜上的集合名
func RankingMongoCollectionName(iosCode string) string {
	var lowerIosCode string
	if iosCode == "" {
		lowerIosCode = ""
	} else {
		lowerIosCode = strings.ToLower(iosCode)
	}

	return "ranking_" + lowerIosCode
}

// 添加用户到排行榜
func RankingAdd(gameDb *fnsvr.Mogo, openid string, mainBk *mainBlock.Data) error {

	mainBk.PreLoad(
		mainBlock.Key_RankingTeam,
		mainBlock.Key_Nickname,
		mainBlock.Key_ChooseSkinId,
		mainBlock.Key_ChooseSkinIdx,
		mainBlock.Key_Face,
	)

	iosCode, err := mainBk.RankingTeam()
	if err != nil {
		return err
	}

	face, err := mainBk.Face()
	if err != nil {
		return err
	}

	name, err := mainBk.Nickname()
	if err != nil {
		return err
	}

	skinId, err := mainBk.ChooseSkinId()
	if err != nil {
		return err
	}
	skinIdx, err := mainBk.ChooseSkinIdx()
	if err != nil {
		return err
	}

	dbid, err := fnsvr.GenerateMongoDbId(openid)
	if err != nil {
		return err
	}

	doc := &MongoRankingUserInfo{
		ID: dbid,
		RankingUserInfo: RankingUserInfo{
			Name:    name,
			OpenId:  openid,
			SkinId:  skinId,
			SkinIdx: skinIdx,
			Face:    face,
		},
	}

	collectionName := RankingMongoCollectionName(iosCode)
	_, err = gameDb.InsertOne(collectionName, doc)
	if err == fnsvr.ErrMongoDeadlineExceeded {
		return fnsvr.ErrMongoDeadlineExceeded
	}

	if err == nil {
		fnsvr.Log().Info("join ranking", "isoCode", iosCode, "dbid", dbid.Hex(), "openid", openid)
	}

	return nil
}

// 清空mongodb排行集合，redis中的数据仍会保留
func ClearMongoRanking(gameDb *fnsvr.Mogo, iosCode string) error {
	collectionName := RankingMongoCollectionName(iosCode)
	collection := gameDb.GetCollection(collectionName)

	// 清空集合
	_, err := collection.DeleteMany(context.Background(), bson.M{})
	if err != nil {
		return err
	}

	return nil
}

const (
	MaxLoadCityRankingPlayerCount = 31 //每个城市装载的玩家数据上限
)

// 缓存用户排行榜到redis
func GetCityRankingPlayerList(gameDb *fnsvr.Mogo, redisConn *redis.Client, iosCode string) ([]*RankingUserInfo, error) {
	//展示30个，缓存31个，客户端判断从榜上排除自己

	// 构建聚合管道
	pipeline := mongo.Pipeline{
		{{
			Key: "$sample",
			Value: bson.D{{
				Key:   "size",
				Value: MaxLoadCityRankingPlayerCount,
			}},
		}},
	}

	collectionName := RankingMongoCollectionName(iosCode)
	collection := gameDb.GetCollection(collectionName)
	cursor, err := collection.Aggregate(context.TODO(), pipeline)
	if err != nil {
		return nil, err
	}
	defer cursor.Close(context.TODO())

	// 处理结果
	var results []*MongoRankingUserInfo
	if err = cursor.All(context.TODO(), &results); err != nil {
		return nil, err
	}

	list := []*RankingUserInfo{}
	for _, info := range results {
		list = append(list, &info.RankingUserInfo)
	}

	return list, nil
}
